/**
 * 2017年11月13日
 */
package exp.algorithm.sic.feature;

import java.util.ArrayList;
import java.util.List;

import exp.algorithm.sic.ScalePeak;
import exp.algorithm.sic.TimeSeries;

/**
 * 线程安全
 * @author Alex
 *
 */

public class ShapeFeatureMaker extends SegmentedSupport{
	

	@Override
	public List<FeatureVector> createFeatureDescriptor(List<ScalePeak> peaks, TimeSeries[] tss) {
		ArrayList<FeatureVector> rr = new ArrayList<>(peaks.size());
		//计算向量应该具有的长度
		int vecLength = PEAKNUM + PEAKNUM-1 + PEAKNUM/2;
		for(ScalePeak s:peaks){
			int spx = s.x;
			float[]v = new float[vecLength];
			int segXs[][] = getSegmentedStartIndex(spx, tss[s.level]);
			//因为边界问题导致特征点减少,所以填充向量的时候要考虑偏移
			int leftNum = segXs[1][0];
			
			//调整偏移
			int offset = 0;
			if(leftNum!=N){
				offset += (N-leftNum);
			}
			int xs[] = segXs[0];
			int beginX = offset;
			for(int i = 0 ;i<xs.length;i++){
				
				v[offset] = fillSlope(i,M,tss[s.level]);
				offset++;
				//offset+=xs.length*3;
			}
			for(int i = beginX;i<xs.length-1;i++){
				v[offset] = fillSlopeRatio(i,v);
				offset ++ ;
			}
			//fill cos
			int numCos = Math.min(segXs[1][0], segXs[1][1]);
			for(int i = 0;i<numCos;i++){
				v[offset] = fillCos(spx-i*M,spx,spx+i*M,tss[s.level]);
				offset ++ ;
			}
			rr.add(new DenseFeatureVector(v));
		}
		
		return rr;

	}
	float fillSlope(int x,int seg,TimeSeries ts){
		//防止除0异常
		return ts.data[x+seg-1]/(ts.data[x] == 0?0.0001f:ts.data[x]);
	}
	float fillSlopeRatio(int x,float[] v){
		//防止除0异常
		return v[x]/v[x+1];
	}
	float fillCos(int leftX,int pointX,int rightX,TimeSeries ts){
		float lt = _calcLength(ts.data[pointX] - ts.data[leftX],pointX-leftX);
		float rt = _calcLength(ts.data[pointX] - ts.data[rightX],rightX-pointX);	
		float bo = _calcLength(rightX-pointX,ts.data[rightX] - ts.data[leftX]);
		return (float) ( (Math.pow(lt, 2)+Math.pow(rt, 2) - Math.pow(bo, 2))/(2 *lt * rt));
	}
	private float _calcLength(float x,float y){
		x = x>0?x:-x;
		y = y>0?y:-y;
		return (float) Math.sqrt( Math.pow(x,2)+ Math.pow(y,2));
	}

}
